<template>
  <el-form id="t_query_condition" :label-width="labelWidth" :form="state.form" size="default" class="t-query-condition"
    :style="{'grid-template-areas': gridAreas, 'grid-template-columns': `repeat(${colLength}, minmax(220px, ${100 / colLength}%))`}"
    @submit.prevent>
    <el-form-item v-for="(opt, i) in cOpts" :key="i" :label="opt.label" :label-width="opt.labelWidth"
      :style="{gridArea: i}" :class="[opt.className,{'render_label':opt.labelRender}]">
      <!-- 自定义label -->
      <template #label v-if="opt.labelRender">
        <render-comp :createElementFunc="opt.labelRender" />
      </template>
      <!-- 自定义输入框插槽 -->
      <template v-if="opt.slotName">
        <slot :name="opt.slotName" :param="state.form"></slot>
      </template>
      <OptComponent v-bind="opt" v-if="!opt.slotName" :opt="opt" :form="state.form" :value="state.form[opt.dataIndex]"
        @change="changeHandler" />
    </el-form-item>
    <el-form-item v-if="Object.keys(cOpts).length > 0" label-width="0" style="grid-area: submit_btn"
      :class="{'flex_end': cellLength % colLength === 0}">
      <el-button type="primary" size="default" class="btn_check" @click="checkHandle" :loading="loading">查询</el-button>
      <el-button v-if="reset" class="btn_reset" size="default" @click="resetHandle">重置</el-button>
      <slot name="querybar"></slot>
    </el-form-item>
  </el-form>
</template>
<script lang="ts">
export default {
  name: 'TQueryCondition'
}
</script>
<script setup lang="ts">
import OptComponent from './OptComponent.vue'
import RenderComp from './renderComp.vue'
import { computed, ref, watch, onMounted, reactive } from 'vue'
const props = defineProps({
  opts: {
    type: Object,
    required: true,
    default: () => ({})
  },
  labelWidth: {
    type: String,
    default: '110px'
  },
  loading: {
    type: Boolean,
    default: false
  },
  reset: {
    type: Boolean,
    default: true
  },
  boolEnter: {
    type: Boolean,
    default: true
  }
})
// 初始化表单数据
let state = reactive({
  form: Object.keys(props.opts).reduce((acc: any, field: any) => {
    acc[field] = props.opts[field].defaultVal || null
    return acc
  }, {})
})
let colLength = ref(0)
const cOpts = computed(() => {
  return Object.keys(props.opts).reduce((acc: any, field: any) => {
    let opt = {
      ...props.opts[field]
    }
    opt.dataIndex = field
    acc[field] = opt
    return acc
  }, {})
})
const cellLength: any = computed(() => {
  // 占用单元格长度
  let length = 0
  Object.keys(props.opts).forEach(key => {
    let span = props.opts[key].span > 4 ? 4 : props.opts[key].span || 1
    length += span
  })
  return length
})
const gridAreas = computed(() => {
  // grid布局按钮位置
  let template = "'. . . .'"
  switch (colLength.value) {
    case 3:
      template = "'. . .'"
      break
    case 2:
      template = "'. .'"
      break
  }
  let areas = [template]
  Object.keys(props.opts).forEach(key => {
    // 根据控件描述注定占用多少列及顺序
    let span = 1
    if (props.opts[key].span > 1 || props.opts[key].span <= 2) {
      // 最多占用2列
      span = props.opts[key].span
    }
    // 计算剩余多少未占用的位置
    let count = 0
    let scrstr = areas[areas.length - 1]
    while (scrstr.indexOf('.') !== -1) {
      scrstr = scrstr.replace(/\./, '')
      count++
    }
    // 若剩余位置不足以放下下一个控件
    if (count < span) {
      areas.push(template)
    }
    let i = 0
    while (i < span) {
      areas[areas.length - 1] = areas[areas.length - 1].replace(/\./, key)
      i++
    }
  })
  // 若控件正好占满一行时，补充多一列放置btn
  if (areas[areas.length - 1].indexOf('.') === -1) {
    areas.push(template)
  }
  if (cellLength.value % colLength.value === 0) {
    // 正好占满一行
    areas[areas.length - 1] = areas[areas.length - 1].replace(
      /\.'$/,
      "submit_btn'"
    )
  } else {
    areas[areas.length - 1] = areas[areas.length - 1].replace(
      /\./,
      'submit_btn'
    )
  }
  return (areas + '').replace(/,/g, '')
})
// 初始化表单数据
const initForm = (opts: any, keepVal = false) => {
  return Object.keys(opts).reduce((acc, field) => {
    if (keepVal && state.form) {
      acc[field] = state.form[field]
    } else if (opts[field].defaultVal) {
      acc[field] = opts[field].defaultVal
    } else {
      acc[field] = null
    }
    return acc
  }, {})
}
const getColLength = () => {
  // 行列数
  const width = window.innerWidth
  let colLength = 4
  if (width > 768 && width < 1280) {
    colLength = 3
  } else if (width <= 768) {
    colLength = 2
  }
  return colLength
}
// 重置
const resetHandle = () => {
  state.form = initForm(props.opts)
  checkHandle('reset')
}
const emits = defineEmits(['change', 'submit'])
const changeHandler = (v, dataIndex) => {
  state.form[dataIndex] = v
  emits('change', state.form)
}
// 查询
const checkHandle = (flagText: any = false) => {
  emits('submit', state.form, flagText)
}
onMounted(() => {
  colLength.value = getColLength()
  if (props.boolEnter) {
    document.onkeyup = e => {
      // console.log(7777, e)
      let key = e.keyCode
      let pagination = document.querySelectorAll('.el-pagination')
      let isPaginationInputFocus = false
      if (pagination) {
        pagination.forEach(ele => {
          let paginationInputList = ele.getElementsByTagName('input')
          let paginationInput =
            paginationInputList[paginationInputList.length - 1]
          // 判断是否有分页器筛选输入框获取焦点
          if (paginationInput === document.activeElement) {
            isPaginationInputFocus = true
          }
        })
      }
      if (isPaginationInputFocus) {
        return
      }
      if (key === 13) {
        checkHandle()
      }
    }
  }
})
watch(
  () => props.opts,
  (opts, oldValue) => {
    state.form = initForm(opts, true)
  }
)

</script>

<style lang="scss">
.t-query-condition.el-form {
  position: relative;
  display: grid;
  gap: 2px 8px;
  margin-bottom: -7px;
  text-align: left;

  .el-select,
  .el-date-editor,
  .ant-calendar-picker {
    width: 100%;
  }

  .flex_end {
    grid-area: submit_btn;
    margin-top: 2px;

    .el-form-item__content {
      display: flex;
      justify-content: flex-end;
      align-items: center;
      overflow: visible !important;
    }
  }

  .el-form-item {
    display: flex;
    margin-bottom: 6px;

    .el-form-item__label {
      flex-shrink: 0;
      min-width: 60px;
      padding-left: 8px;
    }

    .el-form-item__content {
      flex-grow: 1;
      // overflow: hidden;
      margin-left: 0 !important;
    }
  }

  .render_label {
    .el-form-item__label {
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: flex-end;

      &::before {
        margin-top: 1px;
      }
    }
  }

  .btn_check {
    position: relative;
    top: -1px;
  }

  .btn_reset {
    position: relative;
    top: -1px;
    margin-left: 8px;
  }
}
</style>
